! function(win) {
	var __cookie = {
		get: function(name) {
			var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
			if(arr = document.cookie.match(reg)) {
				return unescape(arr[2]);
			} else {
				return false;
			}
		},
		del: function(name) {
			if(this.get(name)) {
				document.cookie = name + '=' + this.get(name) + ';expires=' + (new Date(0)).toGMTString() + '; path=/';
			}
		},
		clear: function() {
			var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
			if(keys) {
				for(var i = keys.length; i--;) {
					document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString() + '; path=/';
				}
			}
		},
		set: function(name, value, time) {
			var exp = new Date();
			exp.setTime(exp.getTime() + (time || 60 * 60 * 1000));
			document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString() + '; path=/';
		},
		all: function() {
			return document.cookie;
		}
	};

	var __storage = {
		jude: (window.Storage && window.localStorage && window.localStorage instanceof Storage ? true : false),
		set: function(name, value, time) {
			if(this.jude == true) {
				var now = new Date().getTime(),
					end = now + (time || 1000 * 60 * 60);
				var data = {
					'data': value,
					'time': end
				};
				data = JSON.stringify(data);
				win.localStorage.setItem(name, data);
			} else {
				return 'Browser does not support "localStorage"';
			}
		},
		get: function(name) {
			if(this.jude == true) {
				var _storage = win.localStorage.getItem(name);
				if(_storage) {
					_storage = JSON.parse(_storage);
					var now = new Date().getTime();
					if(_storage.time >= now) {
						return _storage.data;
					} else {
						this.del(name);
					}
				}
				return false;
			} else {
				return 'Browser does not support "localStorage"';
			}
		},
		del: function(name) {
			if(this.jude == true) {
				win.localStorage.removeItem(name);
			} else {
				return 'Browser does not support "localStorage"';
			}
		},
		clear: function() {
			if(this.jude == true) {
				win.localStorage.clear();
			} else {
				return 'Browser does not support "localStorage"';
			}
		}
	};

	// console dir
	var _P = function() {
		if(__cookie.get('isDebug') == 'on' && typeof console == 'object') {
			if(arguments.length > 1) {
				console.log(arguments[0], arguments[1]);
			} else {
				console.dir(arguments[0]);
			}
		}
	};

	/*
	 * 增强方法，获取年月日时分秒，多种格式
	 * example: formatDate('yy-mm-dd hh:ii:ss', 1486623999);
	 *          formatDate('yy年mm月dd日 hh时ii分ss秒', 1486623999);
	 *          formatDate('yy年mm月dd日', 1486623999);
	 *          or more use method...
	 * */
	var formatDate = function() {
		var dateType = 'yy-mm-dd hh:ii:ss',
			dateTime = new Date().getTime(),
			reg_xx,
			reg_x,
			xx = '',
			x = '';

		if(arguments.length == 1) {
			if(typeof arguments[0] == 'string') {
				dateType = arguments[0];
			} else {
				dateTime = arguments[0];
			}
		} else {
			dateType = arguments[0];
			dateTime = arguments[1];
		}

		if(dateTime.toString().length <= 10) {
			dateTime = parseInt(dateTime) * 1000;
		} else {
			dateTime = parseInt(dateTime);
		}
		dateTime = new Date(dateTime);

		/*format: yyyy*/
		reg_xx = /yy{1}/gi;
		reg_x = /y{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getFullYear();
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getFullYear();
			dateType = dateType.replace(reg_x, x);
		}

		/*format: mm|m*/
		reg_xx = /mm{1}/gi;
		reg_x = /m{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getMonth() + 1 > 9 ? dateTime.getMonth() + 1 : '0' + (dateTime.getMonth() + 1);
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getMonth() + 1;
			dateType = dateType.replace(reg_x, x);
		}

		/*format: dd|d*/
		reg_xx = /dd{1}/gi;
		reg_x = /d{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getDate() > 9 ? dateTime.getDate() : '0' + dateTime.getDate();
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getDate();
			dateType = dateType.replace(reg_x, x);
		}

		/*format: hh|h*/
		reg_xx = /hh{1}/gi;
		reg_x = /h{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getHours() > 9 ? dateTime.getHours() : '0' + dateTime.getHours();
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getHours();
			dateType = dateType.replace(reg_x, x);
		}

		/*format: ii|i*/
		reg_xx = /ii{1}/gi;
		reg_x = /i{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getMinutes() > 9 ? dateTime.getMinutes() : '0' + dateTime.getMinutes();
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getMinutes();
			dateType = dateType.replace(reg_x, x);
		}

		/*format: ss|s*/
		reg_xx = /ss{1}/gi;
		reg_x = /s{1}/gi;
		if(reg_xx.test(dateType)) {
			xx = dateTime.getSeconds() > 9 ? dateTime.getSeconds() : '0' + dateTime.getSeconds();
			dateType = dateType.replace(reg_xx, xx);
		} else if(reg_x.test(dateType)) {
			x = dateTime.getSeconds();
			dateType = dateType.replace(reg_x, x);
		}

		return dateType;
	};

	//get url parameter
	var GetQueryString = function(name) {
		var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
		var r = window.location.search.substr(1).match(reg);
		if(r != null) return unescape(r[2]);
		reg = location.pathname;
		if(reg.indexOf(name) < 0) return null;
		r = reg.substring(parseInt(reg.indexOf(name) + name.length + 1));
		r = r.split('/')[0];
		r = r.split('?')[0];
		if(r != null) return r;
		return null;
	};

	// get url search
	var getSearch = function() {
		var name = arguments[0] || '',
			dec = arguments[1] || '';
		var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"),
			r = window.location.search.substr(1).match(reg);
		if(r != null) {
			if(dec == '') return r[2];
			if(dec == 'unescape' || dec === 1) return unescape(r[2]); // escape
			if(dec == 'decodeURI' || dec === 2) return decodeURI(r[2]); // encodeURI
			if(dec == 'decodeURIComponent' || dec === 3) return decodeURIComponent(r[2]); // encodeURIComponent
		}
		return null;
	}

	// option extend
	var optionExtend = function(opt, opts) {
		if(typeof opts == 'undefined') return(opt);
		if(typeof opt == 'undefined') opt = {};
		for(var i in opts) {
			if(typeof opts[i] == 'object') {
				opt[i] = arguments.callee(opt[i], opts[i]);
			} else {
				opt[i] = opts[i];
			}
		}
		return opt;
	};

	// 停止冒泡
	var stopPropagation = function(e) {
		e = e || window.event;
		if(e.stopPropagation) {
			e.stopPropagation();
		} else {
			e.cancelBubble = true;
		}
	};

	if(window.location.hash == '#isDebug') __cookie.set('isDebug', 'on', 3600000);

	var tool = {
		__cookie: __cookie,

		__storage: __storage,

		p: _P,

		formatDate: formatDate,

		GetQueryString: GetQueryString,

		getSearch: getSearch,

		optionExtend: optionExtend,

		stopPropagation: stopPropagation
	};

	win.tool = tool;

	if(typeof thin != 'undefined' && thin.define) {
		thin.define(function(e) {
			e("tool.amd", tool);
		});
	}
}(window);